#include <cassert>

#include <logger.h>
#include <node_api.h>

/* napi_value */
NAPI_MODULE_INIT(/* napi_env env, napi_value exports */)
{
    // get_instance_data
    void *data = nullptr;
    if (napi_status ret = napi_get_instance_data(env, &data); ret == napi_ok) {
        VALUE_LOGGER(data);
    } else {
        VALUE_LOGGER(ret);
    }
    // data: 0

    // set_instance_data
    napi_finalize finalize = [](napi_env env, void *data, void *hint) {
        int *ptr = reinterpret_cast<int *>(data);
        VALUE_LOGGER(*ptr);
        delete ptr;
    };
    int *data1 = new int(1);
    if (napi_status ret = napi_set_instance_data(env, data1, finalize, nullptr); ret == napi_ok) {
    } else {
        VALUE_LOGGER(ret);
    }
    // *ptr: 1

    // get_instance_data again
    if (napi_status ret = napi_get_instance_data(env, &data); ret == napi_ok) {
        VALUE_LOGGER(data);
        if (data != nullptr) {
            VALUE_LOGGER(*reinterpret_cast<int *>(data));
        }
    } else {
        VALUE_LOGGER(ret);
    }
    // data: 0x55717030c5b0
    // *reinterpret_cast<int *>(data): 1

    auto printInt = [](void *data) {
        if (data != nullptr) {
            VALUE_LOGGER(*reinterpret_cast<int *>(data));
        }
    };
    int *data2 = new int(2);
    int *data3 = new int(3);
    assert(napi_add_env_cleanup_hook(env, printInt, data2) == napi_ok);
    assert(napi_add_env_cleanup_hook(env, printInt, data3) == napi_ok);
    assert(napi_remove_env_cleanup_hook(env, printInt, data2) == napi_ok);
    assert(napi_remove_env_cleanup_hook(env, printInt, new int(3)) == napi_ok);
    // *reinterpret_cast<int *>(data): 3
    return exports;
}
